<template>
  <n-card>
    <!--角色查询-->
    <n-form inline :model="queryParams" label-placement="left">
      <n-form-item label="角色名称" path="name">
        <n-input v-model:value="queryParams.roleName" :clearable="true" />
      </n-form-item>
      <n-form-item label="角色状态" path="name">
        <n-select
          v-model:value="queryParams.status"
          style="width: 160px"
          :options="stateTypeList"
          :clearable="true"
        />
      </n-form-item>
      <n-form-item>
        <n-button attr-type="button" @click="reloadTable">查询</n-button>
      </n-form-item>
    </n-form>

    <!--页面表格信息-->
    <BasicTable
      :columns="columns"
      :request="loadDataTable"
      :row-key="(row) => row.id"
      ref="actionTableRef"
      :actionColumn="actionColumn"
      v-model:checked-row-keys="checkedRowKeys"
    >
      <template #tableTitle>
        <n-button type="primary" @click="onOpenAddRole">新增角色</n-button>
      </template>
      <template #toolbar>
        <n-button type="error" @click="onDeleteRoles">批量删除</n-button>
        <n-button class="ml10" @click="onExport">导出</n-button>
      </template>
    </BasicTable>

    <!--新增或修改角色-->
    <n-modal
      :show-icon="false"
      v-model:show="modelInfo.show"
      preset="dialog"
      :title="modelInfo.info.id ? '修改角色' : '新增角色'"
    >
      <n-form
        :model="modelInfo.info"
        ref="postFormRef"
        label-placement="left"
        :label-width="80"
        class="py-4"
        :rules="roleFormRules"
      >
        <n-form-item label="角色名称" path="roleName">
          <n-input placeholder="请输入角色名称" v-model:value="modelInfo.info.roleName" />
        </n-form-item>
        <n-form-item label="状态" path="status">
          <n-radio-group v-model:value="modelInfo.info.status">
            <n-space>
              <n-radio v-for="item in stateTypeList" :key="item.value" :value="item.value">
                {{ item.label }}
              </n-radio>
            </n-space>
          </n-radio-group>
        </n-form-item>
        <n-form-item label="菜单权限" path="status">
          <n-tree
            ref="menuTreeRef"
            style="width: 100%; border: 1px solid rgba(229, 231, 235); border-radius: 5px"
            checkable
            cascade
            :data="menuTree"
            label-field="name"
            key-field="id"
            :checked-keys="menuTreeSelectedKeys"
            @update:checked-keys="
              (keys) => {
                menuTreeSelectedKeys = keys;
              }
            "
            @update:indeterminate-keys="
              (keys) => {
                menuTreeHalfSelectedKeys = keys;
              }
            "
          />
        </n-form-item>
        <n-form-item label="数据范围" path="status">
          <n-select v-model:value="modelInfo.info.dataScope" :options="dataScopeList" />
        </n-form-item>
        <n-form-item label="备注" path="date">
          <n-input type="textarea" v-model:value="modelInfo.info.remark" />
        </n-form-item>
      </n-form>
      <template #action>
        <n-space>
          <n-button @click="modelInfo.show = false">取消</n-button>
          <n-button type="info" @click="onAddOrEditPost">确认</n-button>
        </n-space>
      </template>
    </n-modal>
  </n-card>
</template>

<script lang="tsx" setup>
  import { h, ref, reactive, nextTick } from 'vue';
  import { BasicTable, TableAction } from '@/components/Table';
  import { useInitDict } from '@/hooks/dictHooks';
  import { NTag, NButton, useMessage } from 'naive-ui';
  import {
    addRoleApi,
    modifyRoleApi,
    getRoleListApi,
    deleteRoleApi,
    deleteRolesApi,
    exportRoleApi,
  } from '@/api/system/role';
  import { getMenuTreeApi } from '@/api/system/menu';
  import {
    debounce,
    deleteNullChildren,
    exportFile,
    getTreeBaseData,
    getArrIntersection,
    getArrDiff,
  } from '@/utils';

  import { activeColumnHooks } from '@/hooks/activeColumnHooks';
  import { messageHooks } from '@/hooks/baseHooks';

  const { message, IDialog } = messageHooks();

  const actionTableRef = ref();
  const postFormRef = ref();
  const roleFormRules = reactive({
    roleName: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }],
  });
  const menuTree = ref([]);
  const menuTreeRef = ref();
  const menuTreeSelectedKeys = ref([]);
  const menuTreeHalfSelectedKeys = ref([]);

  let modelInfo = reactive({
    show: false,
    info: {},
  }); //显示新增修改弹窗

  function resetModelInfo() {
    modelInfo.show = false;
    modelInfo.info = {
      id: undefined,
      roleName: undefined,
      dataScope: 'DEPARTMENT_AND_BELOW',
      remark: undefined,
      status: 'ENABLE',
      menuIdList: [],
    };

    menuTreeSelectedKeys.value = [];
    menuTreeHalfSelectedKeys.value = [];
    onGetTreeMenu();
  }

  function onGetTreeMenu(callBack?: Function) {
    getMenuTreeApi({}).then((res) => {
      if (res && res.code === 'A00000') {
        menuTree.value = deleteNullChildren(res.data);

        if (callBack) {
          callBack();
        }
      }
    });
  }

  //初始化数据字典
  const { stateTypeList, dataScopeList } = useInitDict({
    STATUS_TYPE: 'stateTypeList',
    DATA_SCOPE: 'dataScopeList',
  });

  //定义查询条件
  const queryParams = reactive({
    name: undefined,
    status: undefined,
  });

  //查询表格数据
  function reloadTable() {
    actionTableRef.value.refresh(true);
  }

  //定义表格多选中项
  const checkedRowKeys = ref([]);

  //表格列配置
  const columns = [
    {
      type: 'selection',
      fixed: 'left',
    },
    {
      title: '角色名称',
      key: 'roleName',
      align: 'center',
    },
    {
      title: '角色状态',
      key: 'status',
      render(row) {
        return row.status === 'ENABLE' ? (
          <NTag type="success">启用</NTag>
        ) : (
          <NTag type="error">停用</NTag>
        );
      },
    },
    {
      title: '创建时间',
      key: 'createDate',
      render(row) {
        return <span>{row.createDate}</span>;
      },
    },
    {
      title: '备注',
      key: 'remark',
    },
  ];

  //表格操作列配置
  const { actionColumn } = activeColumnHooks(handleDelete, onOpenEditRole);

  //加载表格数据方法
  const loadDataTable = async (pageation) => {
    let params = {
      pageNum: pageation.current,
      pageSize: pageation.pageSize,

      ...queryParams,
    };

    let res = await getRoleListApi(params);
    return res.data;
  };

  //点击修改按钮
  function onOpenEditRole(record: Recordable) {
    resetModelInfo();
    onGetTreeMenu(() => {
      modelInfo.info = { ...record };
      modelInfo.show = true;

      nextTick(() => {
        const subTree = getTreeBaseData(menuTree.value);

        menuTreeSelectedKeys.value = getArrIntersection(record.menuIdList, subTree);

        let diff = getArrDiff(record.menuIdList, menuTreeSelectedKeys.value);

        menuTreeHalfSelectedKeys.value = diff;
      });
    });
  }

  //点击删除按钮
  function handleDelete(record: Recordable) {
    IDialog.error('你确定删除当前角色?', () => {
      deleteRoleApi(record).then((res) => {
        if (res && res.code === 'A00000') {
          reloadTable();
          message.success(res.msg);
        } else {
          message.error(res.msg);
        }
      });
    });
  }

  /**
   * 批量删除
   */
  function onDeleteRoles() {
    if (checkedRowKeys.value.length === 0) {
      message.warning('请选择角色');
      return;
    }

    IDialog.error('确认批量删除吗？', () => {
      deleteRolesApi(checkedRowKeys.value).then((res) => {
        if (res && res.code === 'A00000') {
          message.success(res.msg);
          reloadTable();
        }
      });
    });
  }

  /**
   * 导出
   */
  const onExport = debounce(function () {
    if (checkedRowKeys.value.length === 0) {
      message.warning('请选择角色');
      return;
    }

    exportRoleApi(checkedRowKeys.value).then((res) => {
      if (res) {
        exportFile('角色.xls', [res]);
        checkedRowKeys.value = [];
      }
    });
  });

  //打开新增角色页面
  function onOpenAddRole() {
    resetModelInfo();
    modelInfo.show = true;
  }

  const onAddOrEditPost = debounce(function () {
    postFormRef.value.validate((errors) => {
      if (!errors) {
        let params = {
          ...modelInfo.info,
          menuIdList: [...menuTreeSelectedKeys.value, ...menuTreeHalfSelectedKeys.value],
        };
        if (params.id === undefined) {
          // 新增角色
          addRoleApi(params).then((res) => {
            if (res.code === 'A00000') {
              message.success(res.msg);
              modelInfo.show = false;
              reloadTable();
            } else {
              message.error(res.msg);
            }
          });
        } else {
          // 修改角色
          modifyRoleApi(params).then((res) => {
            if (res.code === 'A00000') {
              message.success(res.msg);
              modelInfo.show = false;
              reloadTable();
            } else {
              message.error(res.msg);
            }
          });
        }
      }
    });
  });
</script>

<style scoped></style>
